import Net from "../../experience/api/Net.js";
import Api from "../../experience/api/Api.js"
import Algo from "../../experience/utils/Algorithm.js"
import Emitter from "../../experience/utils/Emitter.js";
import Db from "../../experience/db/Db.js"
import Drawer from "../../experience/drawer/Drawer.js"
import Utils from "../../experience/utils/Utils.js"
import { LayerType, ServiceType } from '../../experience/db/Type.js'
import Type from "../../experience/db/Type.js";


const Mine_Id = ServiceType.Mine_Id


export default class SensorUtils {
    constructor() {
        if (SensorUtils.instance) {
            return SensorUtils.instance;
        }
        SensorUtils.instance = this;

        this.net = new Net();
        this.api = new Api();
        this.db = new Db();
        this.algo = new Algo();
        this.drawer = new Drawer();
        this.utils = new Utils();
        this.emitter = new Emitter();

        const ipReg =  /^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/;
        const portReg = /^([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-4]\d{4}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/;
        const urlIp = this.utils.getUrlParamer('ip');
        const urlPort = this.utils.getUrlParamer('port');
        if(ipReg.test(urlIp) && portReg.test(urlPort)) {
            this.BASE_URL = `http://${urlIp}:${urlPort}`;
        } else {
            // 使用默认的 ip，端口
            this.BASE_URL = `http://${location.host}`;
        }
    }

    // 根据地下广播站id 获取单个广播站的详细信息
    async getBroadcastInfo(node_id,serviceType) {
        return await this.net.get(`${this.BASE_URL}/sm_info`, {node_id,serviceType});
    }


    // 获取通风设备信息
    async getSmVentilation() {
        return await this.net.get(`${this.BASE_URL}/ventilation`);
    }

    // 获取通风设备 的所有风向角度信息。有的就代表被设置过风向的。没有就代表没有被设置过风向。
    async getSmVentilation_rotation() {
        return await this.net.get(`${this.BASE_URL}/ventilation_rotation`,{meta_id:'person'});
    }

    // 获取已被选择的摄像头的结点
    async setted_video_list() {
        return await this.net.get(`${this.BASE_URL}/settedSmData`, {type:'video'});
    }

    // 获取已被选择的传感器，监控分站的结点
    async setted_sensor_list() {
        return await this.net.get(`${this.BASE_URL}/settedSmData`, {type:'gas'});
    }

    // 获取已被选择的广播分站的结点
    async setted_broadcast_list() {
        return await this.net.get(`${this.BASE_URL}/settedSmData`, {type:'broadcast'});
    }

    // 获取 全部设备的info信息
    async device_infos() {
        return await this.net.get(`${this.BASE_URL}/sm_info`, {node_id:null,serviceType:null});
    }




    // 获取最新数据更新 indexDB中和安全监控相关的表格数据
    async PositionDbRefresh() {
        // 获取 m_position中的信息 进行更新
        const { data: positions } = await this.api.getSmPositions(ServiceType.Mine_Id);

        // 获取在自己的数据库里面存放着的断电区域的位置信息
        const currentVideoPos = positions.filter((po) => {
            return po.layer === LayerType.SMVideo;
        })
        const currentBroadCastPos = positions.filter((po) => {
            return po.layer === LayerType.SMBroadCast;
        })
        const currentGasPos = positions.filter((po) => {
            return po.layer === LayerType.SMGas;
        })

        // 根据 筛选后的数据，去更新indexDb
        await this.db.refresh(LayerType.SMBroadCast,currentBroadCastPos);
        await this.db.refresh(LayerType.SMVideo,currentVideoPos);
        await this.db.refresh(LayerType.SMGas,currentGasPos);

        // indexDb更新完成以后，自动更新 gis图层上的内容
        await this.drawer._safeMonitorBroadcast();
        await this.drawer._safeMonitorGas();
        this.drawer.initCluster();
    }

    // 获取 传感器与广播站，摄像头断点区域的关联关系
    async getGasintegration() {
        return await this.net.get(`${this.BASE_URL}/integration`)
    }

    // 创建 gis元素高亮动画效果
    highLightAnimation(coordinate, el, time=3000) {
        // 根据传入的 type 值确定，波纹动画效果 是定位时候的波纹还是报警时候的波纹
        const point_div = document.createElement('div');
        let AnimationClassname = 'css_animation_station';

        if(el.type === '传感器') {
            AnimationClassname = 'css_animation_sensor';
        } else if(el.type === '广播站') {
            AnimationClassname = 'css_animation_broadcast';
        } else if(el.type === '人员分站' || el.type === '监控分站') {
            AnimationClassname = 'css_animation_station';
        }

        point_div.className= AnimationClassname;
        const point_overlay = new ol.Overlay({
            element: point_div,
            positioning: 'center-center',
            // 让鼠标点击可以穿透 overlay
            stopEvent:false
        });
        this.drawer.map.addOverlay(point_overlay);

        const x = this.algo.normalX(coordinate[0]);
        const y = this.algo.normalY(coordinate[1]);
        const deNormalCoordinate = [x, y];
        point_overlay.setPosition(deNormalCoordinate);
        const timer = setTimeout(() => {
            this.drawer.map.removeOverlay(point_overlay);
            point_div.remove();
            clearTimeout(timer);
        }, time);
    }

    // 单击树节点的时候，进行元素在gis上的定位
    featureLocate(coordinate, el) {
        const view = this.drawer.map.getView();
        const x = this.algo.normalX(coordinate[0]);
        const y = this.algo.normalY(coordinate[1]);
        const denormalCoordinate = [x, y];
        view.setCenter(denormalCoordinate);
        this.highLightAnimation(coordinate, el);

        // 定位的时候,还需要将信息弹窗弹出来，元素小点点的顶部还需要出现浮动的高亮图标。
        if(el.type === '监控分站' || el.type === '传感器') {
            this.emitter.emit("smgas-feature-click", el.node_id);
        } else if(el.type === '广播站') {
            this.emitter.emit("smbroadcast-feature-click", el.node_id);
        } else if(el.type === '摄像头') {
            this.emitter.emit("smvideo-feature-click", el.node_id);
        }
    }

    // 用线条连接体现监控分站下 传感器的从属关系 (传入的node_id 必须是监控分站)
    highLightStationRelation(treenode) {
        const {node_id} = treenode, childrenSensor = [];
        const features = this.drawer.source(LayerType.SMGas).getFeatures();

        let stationFeature = null;
        features.forEach((f) => {
            if(f.get('parent_id') === node_id) { childrenSensor.push(f); }
            if(f.get('node_id') === node_id) { stationFeature = f; }
        });

        const stationCoordinate = stationFeature.getGeometry().getCoordinates();
        const sensorChilrenCoordinate = childrenSensor.map((point) => {
            return point.getGeometry().getCoordinates();
        });

        const modifySource = this.drawer.source(Type.Modify)
        const insertFeatures = sensorChilrenCoordinate.map((co) => {
            const lineFe = new ol.Feature();
            const geom = new ol.geom.LineString([co,stationCoordinate]);
            lineFe.setGeometry(geom);
            return lineFe;
        })

        modifySource.addFeatures(insertFeatures);
        const timer = setTimeout(() => {
            modifySource.clear();
            clearTimeout(timer);
        },3500);
    }

    // 用线条连接体现监控分站下 与传入传感器 属于同一个通道的所有传感器
    highLightSensorRelation(treenode) {
        const { sensor_Type, station_Id, node_id, channel_Code, channel_Id } = treenode;
        const features = this.drawer.source(LayerType.SMGas).getFeatures()
        const nodes = []
        features.forEach((f) => {
            if(f.get('station_Id') === station_Id && f.get('channel_Id') === channel_Id) {
                nodes.push(f);
            }
        });

        // 按照 channelcode排序
        nodes.sort(function (a, b) {
            const a_code = a.get('channel_Code');
            const b_code = b.get('channel_Code');
            return a_code - b_code;
        });

        const nodesCoordinate = nodes.map(point => point.getGeometry().getCoordinates());
        const multiLineCoordinates = [];
        for(let i = 0;0 < nodesCoordinate.length; i++) {
            if(i === nodesCoordinate.length - 1) break;
            multiLineCoordinates.push([nodesCoordinate[i], nodesCoordinate[i+1]]);
        }

        const modifySource = this.drawer.source(Type.Modify);
        const multiLineFeature =  new ol.Feature();
        multiLineFeature.setGeometry(new ol.geom.MultiLineString(multiLineCoordinates));
        modifySource.addFeature(multiLineFeature);
        const timer = setTimeout(() => {
            modifySource.clear();
            clearTimeout(timer);
        },3500);
    }

    // 根据两个相对坐标点 返回实际的偏转角度(用于计算风向角度的)
    get_rel_rotation(end_pos, start_pos, slope) {
        // 生成线段的方向向量
        const lineVector = [end_pos[0] - start_pos[0], end_pos[1] - start_pos[1]];
        let arrowVal = 0;
        if(lineVector[0] < 0) {
            console.log('atan',Math.atan(slope));
            arrowVal = Math.atan(slope) + Math.PI;
        } else if(lineVector[0] > 0) {
            console.log('atan',Math.atan(slope));
            arrowVal = Math.atan(slope);
        } else {
            if(lineVector[1] < 0) { arrowVal = - Math.PI * 0.5; }
            if(lineVector[1] > 0) { arrowVal = Math.PI * 0.5; }
        }
        return arrowVal;
    }

    // 把所有的除底图以外的所有的gis元素的文本都隐藏掉
    hideFeatureText() {
        const video = this.drawer.source(LayerType.SMVideo).getFeatures()
        const broadcast = this.drawer.source(LayerType.SMBroadCast).getFeatures()
        const gas = this.drawer.source(LayerType.SMGas).getFeatures()
        const mergeFeatures = [...video, ...broadcast, ...gas];
        mergeFeatures.forEach((f) => {
            const style = f.getStyle()
            const text = style.getText()
            text.setText('')
            style.setText(text)
            f.setStyle(style)
        })
    }

    // 把所有的除底图以外的所有的gis元素的文本都显示出来
    showFeatureText() {
        const video = this.drawer.source(LayerType.SMVideo).getFeatures();
        const broadcastFeatures = this.drawer.source(LayerType.SMBroadCast).getFeatures();
        const gas = this.drawer.source(LayerType.SMGas).getFeatures();
        const features = [...video, ...broadcastFeatures, ...gas];
        features.forEach((f) => {
            const style = f.getStyle();
            const text = style.getText();
            text.setText(f.get('show_text'));
            style.setText(text);
            f.setStyle(style);
        });
    }

    uuid() {
        const s = [];
        const hexDigits = "0123456789abcdef";
        for (let i = 0; i < 32; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }

        // bits 12-15 of the time_hi_and_version field to 0010
        s[14] = "4";

        // bits 6-7 of the clock_seq_hi_and_reserved to 01
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
        s[8] = s[13] = s[18] = s[23];
        return s.join("");
    }

    // 对列表进行分页的函数
    paginize(list,page_num,page_size) {
        const page_count = Math.ceil(list.length / page_size)
        const startIndex = (page_num - 1) * page_size, endIndex = startIndex + page_size
        const page_list = list.slice(startIndex,endIndex)
        return {page_list,page_count,page_num}
    }
}
